﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

// Directive for the data model
using Angerona.Model;
using System;
using System.Windows;
using System.IO.IsolatedStorage;
using Microsoft.Phone.Scheduler;

namespace Angerona.ViewModel
{
    public class AngeronaViewModel : INotifyPropertyChanged
    {
        // Linq to SQL datacontext
        public AngeronaDataContext angeronaDB;

        // Class constructor
        public AngeronaViewModel(string angeronaDBConnectionString)
        {
            angeronaDB = new AngeronaDataContext(angeronaDBConnectionString);
        }

        // Write changes in to the data context to the database
        public void SaveChangesToDB()
        {
            angeronaDB.SubmitChanges();
            //angeronaDB.Dispose();
        }

        // DROP THE (DATA)BASS
        public void ResetDatabase()
        {
            foreach (VehiclesTable Vehicle in AllVehicles)
            {
                ScheduledAction OldReminder = ScheduledActionService.Find("AssuranceDate" + Vehicle.VehicleName);
                if (OldReminder != null)
                    ScheduledActionService.Remove(OldReminder.Name);

                ScheduledAction OldReminder2 = ScheduledActionService.Find("Bollo" + Vehicle.VehicleName);
                if (OldReminder2 != null)
                    ScheduledActionService.Remove(OldReminder2.Name);

                ScheduledAction OldReminder3 = ScheduledActionService.Find("Revision" + Vehicle.VehicleName);
                if (OldReminder3 != null)
                    ScheduledActionService.Remove(OldReminder3.Name);

                // Deleting car image from isostore
                if (Vehicle.ImageOfCar != null)
                {
                    using (IsolatedStorageFile myIsoStoreFile = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        myIsoStoreFile.DeleteFile(Vehicle.ImageOfCar);
                    }
                }
            }

            angeronaDB.Vehicles.DeleteAllOnSubmit<VehiclesTable>(AllVehicles);
            //angeronaDB.Fuel.DeleteAllOnSubmit<FuelData>(AllFuel);
            //angeronaDB.Maintenance.DeleteAllOnSubmit<MaintenanceData>(AllMaintenance);
            //angeronaDB.Generic.DeleteAllOnSubmit<GenericData>(AllGeneric);
            angeronaDB.DeleteDatabase();
            angeronaDB.CreateDatabase();

            // Cancellazione dell'utente da inserire
            //Delete a previous reminder, only if is same reminder
            ScheduledAction OldReminderU = ScheduledActionService.Find("LicenseExpired");
            if (OldReminderU != null)
                ScheduledActionService.Remove(OldReminderU.Name);

            IsolatedStorageSettings.ApplicationSettings.Remove("uname");
            IsolatedStorageSettings.ApplicationSettings.Remove("usurname");
            IsolatedStorageSettings.ApplicationSettings.Remove("licensenum");
            IsolatedStorageSettings.ApplicationSettings.Remove("licensepoint");
            IsolatedStorageSettings.ApplicationSettings.Remove("licenserelease");
            IsolatedStorageSettings.ApplicationSettings.Remove("licenseexpire");
            IsolatedStorageSettings.ApplicationSettings.Remove("licensecategory");
            IsolatedStorageSettings.ApplicationSettings.Remove("licenserextriction");

        }

        public void ResetAllCars()
        {
            foreach (VehiclesTable Vehicle in AllVehicles)
            {
                ScheduledAction OldReminder = ScheduledActionService.Find("AssuranceDate" + Vehicle.VehicleName);
                if (OldReminder != null)
                    ScheduledActionService.Remove(OldReminder.Name);

                ScheduledAction OldReminder2 = ScheduledActionService.Find("Bollo" + Vehicle.VehicleName);
                if (OldReminder2 != null)
                    ScheduledActionService.Remove(OldReminder2.Name);

                ScheduledAction OldReminder3 = ScheduledActionService.Find("Revision" + Vehicle.VehicleName);
                if (OldReminder3 != null)
                    ScheduledActionService.Remove(OldReminder3.Name);

                // Deleting car image from isostore
                if (Vehicle.ImageOfCar != null)
                {
                    using (IsolatedStorageFile myIsoStoreFile = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        myIsoStoreFile.DeleteFile(Vehicle.ImageOfCar);
                    }
                }
            }
            angeronaDB.Vehicles.DeleteAllOnSubmit<VehiclesTable>(AllVehicles);
            angeronaDB.DeleteDatabase();
            angeronaDB.CreateDatabase();
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        // Used to notify Silverlight that a property has changed;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        // Load ALL elements in ALL tables

        public void LoadCollectionsFromDatabase()
        {
            var ItemsInDB = from VehiclesTable vt in angeronaDB.Vehicles
                            select vt;
            var ItemsInFuelDB = from FuelData ft in angeronaDB.Fuel
                                select ft;
            var ItemsInGenericDB = from GenericData gt in angeronaDB.Generic
                                   select gt;
            var ItemsInMaintenanceDB = from MaintenanceData mt in angeronaDB.Maintenance
                                       select mt;
            AllVehicles = new ObservableCollection<VehiclesTable>(ItemsInDB);
            AllFuel = new ObservableCollection<FuelData>(ItemsInFuelDB);
            AllGeneric = new ObservableCollection<GenericData>(ItemsInGenericDB);
            AllMaintenance = new ObservableCollection<MaintenanceData>(ItemsInMaintenanceDB);
        }


        // VEHICLE TABLE SPECIFIC
        //
        private ObservableCollection<VehiclesTable> _allVehicles;
        public ObservableCollection<VehiclesTable> AllVehicles
        {
            get { return _allVehicles; }
            set
            {
                _allVehicles = value;
                NotifyPropertyChanged("AllVehicles");
            }
        }

        public void AddItem(VehiclesTable newVehiclesItem)
        {
            // Add a to-do item to the data context.
            angeronaDB.Vehicles.InsertOnSubmit(newVehiclesItem);

            // Save changes to the database.
            angeronaDB.SubmitChanges();

            // Add a to-do item to the "all" observable collection.
            AllVehicles.Add(newVehiclesItem);
        }

        public void DeleteItem(VehiclesTable forDelete)
        {
            while (forDelete.Refueling.Count() > 0)
                DeleteRefill(forDelete.Refueling.FirstOrDefault());

            while (forDelete.GenericEntitySet.Count() > 0)
                DeleteGeneric(forDelete.GenericEntitySet.FirstOrDefault());

            while (forDelete.MaintenanceEntitySet.ToList().Count() > 0)
                DeleteMaintenance(forDelete.MaintenanceEntitySet.FirstOrDefault());

            // Remove the item from the "all" observable collection.
            AllVehicles.Remove(forDelete);
            // Remove the item from the data context.
            angeronaDB.Vehicles.DeleteOnSubmit(forDelete);

            angeronaDB.SubmitChanges();
        }

        /// <summary>
        /// count the number of vehicles
        /// </summary>
        /// <returns>int #vehicles</returns>
        public int getNumbersOfVehicles()
        {
            return angeronaDB.Vehicles.Count();
        }

        private VehiclesTable _ElementWithID;
        /// <summary>
        /// return the vehicle with match ID
        /// </summary>
        /// <param name="i">ID vehicles</param>
        /// <returns>selected car</returns>
        public VehiclesTable getElementWithID(int i)
        {
            var x = from VehiclesTable t in angeronaDB.Vehicles
                    where t.VId == i
                    select t;
            _ElementWithID = x.FirstOrDefault();
            return _ElementWithID;
        }

        private List<int> _VehicleIdlist;
        /// <summary>
        /// get a list of vehicles ID
        /// </summary>
        /// <returns> list<int> of vehicles ID's</returns>
        public List<int> getVehicleIdlist()
        {
            _VehicleIdlist = (from VehiclesTable t in angeronaDB.Vehicles
                       select t.VId).ToList();
            return _VehicleIdlist;
        }

        //
        // Fuel data SPECIFIC
        //
        //


        // Calcola tutte le spese della macchina
        /// <summary>
        /// Sum all the fuel operations of a specific car
        /// </summary>
        /// <param name="idOfCar">ID of the vehicle</param>
        /// <returns> Float number representing the sum of all fuel spent money of a car </returns>
        public float sumOfAllSpentFuelDataOfCar(int idOfCar)
        {

            var getCar = from FuelData ft in angeronaDB.Fuel
                         where ft._vehicleID == idOfCar
                         select ft;
            float sumOfElements = 0;

            foreach (FuelData elementFuel in getCar)
            {
                sumOfElements += elementFuel.Spent;
            }
            return sumOfElements;
        }

        public float sumOfAllQuantityFuel(int idOfCar)
        {
            var getCar = from FuelData ft in angeronaDB.Fuel
                         where ft._vehicleID == idOfCar
                         select ft;
            float sumOfAllQuantity = 0;

            foreach (FuelData elementFuel in getCar)
            {
                sumOfAllQuantity += elementFuel.Quantity;
            }
            return sumOfAllQuantity;
        }

        //FOR DATE PIKER start
        public List<FuelData> getFuelBetweenDate(int idOfCar, DateTime fromDate, DateTime toDate)
        {
            var x = from FuelData ft in angeronaDB.Fuel
                    where ft._vehicleID == idOfCar & ft.OperationDate <= toDate & ft.OperationDate >= fromDate
                    orderby ft.OperationDate descending
                    select ft;
            return x.ToList();
        }


        public float SpentFuelDataOfCarBetweenDate(int idOfCar, DateTime fromDate, DateTime toDate)
        {
            var x = from FuelData ft in angeronaDB.Fuel
                    where ft._vehicleID == idOfCar & ft.OperationDate <= toDate & ft.OperationDate >= fromDate
                    select ft;
            float sumOfElements = 0;

            foreach (FuelData elementFuel in x)
            {
                sumOfElements += elementFuel.Spent;
            }
            return sumOfElements;
        }
        

        public float sumQuantityFuelBetweenDate(int idOfCar, DateTime fromDate, DateTime toDate)
        {
            var getCar = from FuelData ft in angeronaDB.Fuel
                         where ft._vehicleID == idOfCar & ft.OperationDate <= toDate & ft.OperationDate >= fromDate
                         select ft;
            float sumOfElements = 0;
            foreach (FuelData elementFuel in getCar)
            {
                sumOfElements += elementFuel.Quantity;
            }
            return sumOfElements;
        }
        //FOR DATEPIKER stop


        // Ritorna una lista di fueldata dell'id della macchina
        public List<FuelData> getFuelDataOfCar(int idOfCar)
        {
            var getCar = (from FuelData ft in angeronaDB.Fuel
                         where ft._vehicleID == idOfCar
                         select ft).ToList();
            return getCar;
        }

        private ObservableCollection<FuelData> _allFuel;
        public ObservableCollection<FuelData> AllFuel
        {
            get { return _allFuel; }
            set
            {
                _allFuel = value;
                NotifyPropertyChanged("AllFuel");
            }
        }
        
        // Ritorna tutte le operazioni della tabella FUEL
        public int numbersOfFuelOperations()
        { return angeronaDB.Fuel.Count(); }

        private List<float> _fuelOperations;
        public List<float> getFuelOperationsOfCar(int carId)
        {
            _fuelOperations = (from FuelData ft in angeronaDB.Fuel
                               where ft._vehicleID == carId
                               select ft.Spent).ToList();
            return _fuelOperations;
        }



        public void AddRefill(FuelData newRefill)
        {
            angeronaDB.Fuel.InsertOnSubmit(newRefill);
            angeronaDB.SubmitChanges();
            AllFuel.Add(newRefill);
        }

        public void DeleteRefill(FuelData forDelete)
        {
            AllFuel.Remove(forDelete);
            angeronaDB.Fuel.DeleteOnSubmit(forDelete);
            angeronaDB.SubmitChanges();
        }

        // GENERIC DATA SPECIFIC
        //
        // Ritorna tutte le operazioni generic effettuate dalla macchina con id idOfCar
        public List<GenericData> getGenericDataOfCar(int idOfCar)
        {
            var getCar = (from GenericData gt in angeronaDB.Generic
                          where gt._vehicleID == idOfCar
                          select gt).ToList();
            return getCar;
        }


        // Ritorna la lista di float contenente solo i valori della spesa di generic data.
        private List<float> _genericOperations;
        public List<float> getGenericOperationsOfCar(int carId)
        {
            _genericOperations = (from GenericData gt in angeronaDB.Generic
                                  where gt._vehicleID == carId
                                  select gt.Spent).ToList();
            return _genericOperations;
        }


        private ObservableCollection<GenericData> _allGeneric;
        public ObservableCollection<GenericData> AllGeneric
        {
            get { return _allGeneric; }
            set
            {
                _allGeneric = value;
                NotifyPropertyChanged("AllGeneric");
            }
        }

        //FOR DATEPIKER start
        public List<GenericData> getGenericBetweenDate(int idOfCar, DateTime fromDate, DateTime toDate)
        {
            var x = from GenericData g in angeronaDB.Generic
                    where g._vehicleID == idOfCar & g.OperationDate <= toDate & g.OperationDate >= fromDate
                    orderby g.OperationDate descending
                    select g;
            return x.ToList();
        }

        public float sumQuantityGenericBetweenDate(int idOfCar, DateTime fromDate, DateTime toDate)
        {
            var x = from GenericData g in angeronaDB.Generic
                    where g._vehicleID == idOfCar & g.OperationDate <= toDate & g.OperationDate >= fromDate
                    select g;

            float sumOfElements = 0;
            foreach (GenericData element in x)
            {
                sumOfElements += element.Spent;
            }
            return sumOfElements;
        }


        //FOR DATEPIKER end

        public float sumOfAllGenericCost(int idOfCar)
        {
            var getCar = from GenericData mt in angeronaDB.Generic
                         where mt._vehicleID == idOfCar
                         select mt;
            float sumAll = 0;

            foreach (GenericData elementGeneric in getCar)
            {
                sumAll += elementGeneric.Spent;
            }
            return sumAll;
        }

        public int numberOfGenericOperations()
        { return angeronaDB.Generic.Count(); }

        public void AddGeneric(GenericData newGeneric)
        {
            angeronaDB.Generic.InsertOnSubmit(newGeneric);
            angeronaDB.SubmitChanges();
            AllGeneric.Add(newGeneric);
        }
        public void DeleteGeneric(GenericData forDelete)
        {

            AllGeneric.Remove(forDelete);
            angeronaDB.Generic.DeleteOnSubmit(forDelete);
            angeronaDB.SubmitChanges();
        }

        // MAINTENANCE DATA SPECIFIC
        //

        // Ritorna tutte le operazioni generic effettuate dalla macchina con id idOfCar
        public List<MaintenanceData> getMaintenanceDataOfCar(int idOfCar)
        {
            var getCar = (from MaintenanceData mt in angeronaDB.Maintenance
                          where mt._vehicleID == idOfCar
                          select mt).ToList();
            return getCar;
        }

        // Ritorna la lista di float contenente solo i valori della spesa di maintenance data.
        private List<float> _maintenanceOperations;
        public List<float> getMaintenanceOperationsOfCar(int carId)
        {
            _maintenanceOperations = (from MaintenanceData mt in angeronaDB.Maintenance
                                      where mt._vehicleID == carId
                                      select mt.Spent).ToList();
            return _maintenanceOperations;
        }
        /*
        private List<MaintenanceData> _maintenanceOperationFromDate;
        public List<MaintenanceData> MaintenanceOperationFromDate(int month, int day, int year)
        {
            _maintenanceOperationFromDate = (from MaintenanceData mt in angeronaDB.Maintenance
                                             where mt.OperationDate.Year == year & mt.OperationDate.Month == month & mt.OperationDate.Day == day
                                             select mt).ToList();
            return _maintenanceOperationFromDate;
        }
        */
        private ObservableCollection<MaintenanceData> _allMaintenance;
        public ObservableCollection<MaintenanceData> AllMaintenance
        {
            get { return _allMaintenance; }
            set
            {
                _allMaintenance = value;
                NotifyPropertyChanged("AllMaintenance");
            }
        }

        //FOR DATEPIKER start
        public List<MaintenanceData> getMantinanceBetweenDate(int idOfCar, DateTime fromDate, DateTime toDate)
        {
            var x = from MaintenanceData m in angeronaDB.Maintenance
                    where m._vehicleID == idOfCar & m.OperationDate <= toDate & m.OperationDate >= fromDate
                    orderby m.OperationDate descending
                    select m;
            return x.ToList();
        }

        public float sumQuantityMantinanceBetweenDate(int idOfCar, DateTime fromDate, DateTime toDate)
        {
            var x = from MaintenanceData m in angeronaDB.Maintenance
                    where m._vehicleID == idOfCar & m.OperationDate <= toDate & m.OperationDate >= fromDate
                    select m;

            float sumOfElements = 0;
            foreach (MaintenanceData element in x)
            {
                sumOfElements += element.Spent;
            }
            return sumOfElements;
        }


        //FOR DATEPIKER end

        public float sumOfAllMaintenanceCost(int idOfCar)
        {
            var getCar = from MaintenanceData mt in angeronaDB.Maintenance
                         where mt._vehicleID == idOfCar
                         select mt;
            float sumAll = 0;

            foreach (MaintenanceData elementMaintenance in getCar)
            {
                sumAll += elementMaintenance.Spent;
            }
            return sumAll;
        }

        public int numberOfMaintenanceOperations()
        { return angeronaDB.Maintenance.Count(); }

        public void AddMaintenance(MaintenanceData newMaintenance)
        {
            angeronaDB.Maintenance.InsertOnSubmit(newMaintenance);
            angeronaDB.SubmitChanges();
            AllMaintenance.Add(newMaintenance);
        }
        public void DeleteMaintenance(MaintenanceData forDelete)
        {
            AllMaintenance.Remove(forDelete);
            angeronaDB.Maintenance.DeleteOnSubmit(forDelete);
            angeronaDB.SubmitChanges();
        }
    }
}